import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
import { REACT_CHUNK_NAME } from './const';
import { generateFunction } from '../../../utils/jsExpression';
import {
  BuilderComponentPlugin, BuilderComponentPluginFactory,
  FileType, ICodeChunk, ICodeStruct, IContainerInfo, ChunkType,
} from '../../../types';

export interface PluginConfig {
  fileType?: string;
  exportNameMapping?: Record<string, string>;
  normalizeNameMapping?: Record<string, string>;
  exclude?: string[];
}

const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = () => {
  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
    const next: ICodeStruct = {...pre};
    const ir = next.ir as IContainerInfo;
    const JSXType = FileType.JSX;
    if (ir.lifeCycles) {
      const { lifeCycles } = ir;
      const chunks = Object.keys(lifeCycles).map<ICodeChunk | null>((lifeCycleName) => {
        const normalizeName = lifeCycleName;
        const exportName = lifeCycleName;
        if (normalizeName === 'constructor') {
          return {
            type: ChunkType.STRING,
            fileType: JSXType,
            name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
            content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }),
            linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]],
          };
        } else if (normalizeName === 'componentDidMount') {
          return {
            type: ChunkType.STRING,
            fileType: JSXType,
            name: REACT_CHUNK_NAME.ClassDidMountContent,
            content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }),
            linkAfter: [REACT_CHUNK_NAME.ClassDidMountStart],
          };
        } else if (normalizeName === 'render') {
          return {
            type: ChunkType.STRING,
            fileType: JSXType,
            name: REACT_CHUNK_NAME.ClassRenderPre,
            content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }),
            linkAfter: [REACT_CHUNK_NAME.ClassRenderStart],
          };
        } else { // componentWillUnmount 及其他
          return {
            type: ChunkType.STRING,
            fileType: JSXType,
            name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
            content: generateFunction(lifeCycles[lifeCycleName], {
              name: exportName,
              isMember: true,
            }),
            linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
          };
        }
      }).filter((i) => !!i);
      next.chunks.push(...chunks.filter((x): x is ICodeChunk => x !== null));
    }
    return next;
  };
  return plugin;
};

export default pluginFactory;
